--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
tests/backend/test_access_attempts_dao.py ec74a2651e897325b14269ae52d11b1e12f0b6e2 (ec74a265) Text, 5.21 KB
T8b949e# SPDX-License-Identifier: 0BSD
T8b949e"""Tests and property-based checks for AccessAttemptsDAO."""
Tff7b72from T7ee787__future__ Tff7b72import Te6edf3annotations
Tff7b72import T7ee787time
Tff7b72import T7ee787pytest
Tff7b72from T7ee787hypothesis Tff7b72import Te6edf3HealthCheckTb4b4b4, Te6edf3assumeTb4b4b4, Te6edf3givenTb4b4b4, Te6edf3settings
Tff7b72from T7ee787hypothesis Tff7b72import Te6edf3strategies Tff7b72as Te6edf3st
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787databaseT7ee787.T7ee787access_attempts Tff7b72import Tb4b4b4(
Te6edf3LOGIN_PATHTb4b4b4,
Te6edf3MAX_TRUSTED_FINGERPRINTS_PER_IDENTITYTb4b4b4,
Te6edf3SETUP_PATHTb4b4b4,
Te6edf3AccessAttemptsDAOTb4b4b4,
Te6edf3user_agent_hashTb4b4b4,
Tb4b4b4)
Tff7b72def Td2a8ff_id_hashTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657strTb4b4b4:
Tff7b72return Ta5d6ff"Ta5d6ff746573745f686173685f33325f62797465735f6c6f6e675f3031323334353637Ta5d6ff"
Tf0883e@pytestTff7b72.Td2a8fffixture
Tff7b72def Td2a8ffdaoTb4b4b4(Te6edf3dbTb4b4b4) Tff7b72-Tff7b72> Te6edf3AccessAttemptsDAOTb4b4b4:
Tff7b72return Te6edf3dbTff7b72.Td2a8ffaccess_attempts
Tff7b72def Td2a8fftest_user_agent_hash_deterministicTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72assert Te6edf3user_agent_hashTb4b4b4(Ta5d6ff"Ta5d6ffMozilla/5.0Ta5d6ff"Tb4b4b4) Tff7b72== Te6edf3user_agent_hashTb4b4b4(Ta5d6ff"Ta5d6ffMozilla/5.0Ta5d6ff"Tb4b4b4)
Tff7b72assert Te6edf3user_agent_hashTb4b4b4(Ta5d6ff"Ta5d6ff"Tb4b4b4) Tff7b72== Te6edf3user_agent_hashTb4b4b4(Ta5d6ff"Ta5d6ff"Tb4b4b4)
Tf0883e@settingsTb4b4b4(Te6edf3max_examplesTff7b72=T79c0ff100Tb4b4b4, Te6edf3suppress_health_checkTff7b72=Tb4b4b4[Te6edf3HealthCheckTff7b72.Td2a8fffunction_scoped_fixtureTb4b4b4]Tb4b4b4)
Tf0883e@givenTb4b4b4(Te6edf3sTff7b72=Te6edf3stTff7b72.Td2a8fftextTb4b4b4(Te6edf3min_sizeTff7b72=T79c0ff0Tb4b4b4, Te6edf3max_sizeTff7b72=T79c0ff600Tb4b4b4)Tb4b4b4)
Tff7b72def Td2a8fftest_user_agent_hash_hypothesis_stableTb4b4b4(Te6edf3daoTb4b4b4, Te6edf3sTb4b4b4)Tb4b4b4:
Te6edf3h1 Tff7b72= Te6edf3user_agent_hashTb4b4b4(Te6edf3sTb4b4b4)
Te6edf3h2 Tff7b72= Te6edf3user_agent_hashTb4b4b4(Te6edf3sTb4b4b4)
Tff7b72assert Te6edf3h1 Tff7b72== Te6edf3h2
Tff7b72assert Tffa657lenTb4b4b4(Te6edf3h1Tb4b4b4) Tff7b72== T79c0ff64
Tff7b72def Td2a8fftest_insert_list_roundtripTb4b4b4(Te6edf3daoTb4b4b4)Tb4b4b4:
Te6edf3ih Tff7b72= Te6edf3_id_hashTb4b4b4(Tb4b4b4)
Te6edf3daoTff7b72.Td2a8ffinsertTb4b4b4(Te6edf3ihTb4b4b4, Ta5d6ff"Ta5d6ff10.0.0.1Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffTestAgent/1Ta5d6ff"Tb4b4b4, Te6edf3LOGIN_PATHTb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffsuccessTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Te6edf3rows Tff7b72= Te6edf3daoTff7b72.Td2a8fflist_attemptsTb4b4b4(Te6edf3limitTff7b72=T79c0ff10Tb4b4b4, Te6edf3offsetTff7b72=T79c0ff0Tb4b4b4)
Tff7b72assert Tffa657lenTb4b4b4(Te6edf3rowsTb4b4b4) Tff7b72>Tff7b72= T79c0ff1
Te6edf3top Tff7b72= Te6edf3rowsTb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72assert Te6edf3topTb4b4b4[Ta5d6ff"Ta5d6ffidentity_hashTa5d6ff"Tb4b4b4] Tff7b72== Te6edf3ih
Tff7b72assert Te6edf3topTb4b4b4[Ta5d6ff"Ta5d6ffclient_ipTa5d6ff"Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6ff10.0.0.1Ta5d6ff"
Tff7b72assert Te6edf3topTb4b4b4[Ta5d6ff"Ta5d6ffuser_agentTa5d6ff"Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6ffTestAgent/1Ta5d6ff"
Tff7b72assert Te6edf3topTb4b4b4[Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4] Tff7b72== Te6edf3LOGIN_PATH
Tff7b72assert Te6edf3topTb4b4b4[Ta5d6ff"Ta5d6ffmethodTa5d6ff"Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6ffPOSTTa5d6ff"
Tff7b72assert Te6edf3topTb4b4b4[Ta5d6ff"Ta5d6ffoutcomeTa5d6ff"Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6ffsuccessTa5d6ff"
Tff7b72def Td2a8fftest_count_matches_list_for_no_filtersTb4b4b4(Te6edf3daoTb4b4b4)Tb4b4b4:
Te6edf3ih Tff7b72= Te6edf3_id_hashTb4b4b4(Tb4b4b4)
Te6edf3before Tff7b72= Te6edf3daoTff7b72.Td2a8ffcount_attemptsTb4b4b4(Tb4b4b4)
Te6edf3daoTff7b72.Td2a8ffinsertTb4b4b4(Te6edf3ihTb4b4b4, Ta5d6ff"Ta5d6ff10.0.0.2Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffaTa5d6ff"Tb4b4b4, Te6edf3LOGIN_PATHTb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fffailed_passwordTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Te6edf3after Tff7b72= Te6edf3daoTff7b72.Td2a8ffcount_attemptsTb4b4b4(Tb4b4b4)
Tff7b72assert Te6edf3after Tff7b72== Te6edf3before Tff7b72+ T79c0ff1
Tff7b72def Td2a8fftest_search_filtersTb4b4b4(Te6edf3daoTb4b4b4)Tb4b4b4:
Te6edf3ih Tff7b72= Te6edf3_id_hashTb4b4b4(Tb4b4b4)
Te6edf3daoTff7b72.Td2a8ffinsertTb4b4b4(
Te6edf3ihTb4b4b4,
Ta5d6ff"Ta5d6ff192.168.99.1Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffUniqueSearchUATa5d6ff"Tb4b4b4,
Te6edf3LOGIN_PATHTb4b4b4,
Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffsuccessTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffdetail-xTa5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3found Tff7b72= Te6edf3daoTff7b72.Td2a8fflist_attemptsTb4b4b4(Te6edf3searchTff7b72=Ta5d6ff"Ta5d6ffUniqueSearchUATa5d6ff"Tb4b4b4, Te6edf3limitTff7b72=T79c0ff50Tb4b4b4)
Tff7b72assert Tffa657anyTb4b4b4(Te6edf3rTb4b4b4[Ta5d6ff"Ta5d6ffuser_agentTa5d6ff"Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6ffUniqueSearchUATa5d6ff" Tff7b72for Te6edf3r Tff7b72in Te6edf3foundTb4b4b4)
Te6edf3n Tff7b72= Te6edf3daoTff7b72.Td2a8ffcount_attemptsTb4b4b4(Te6edf3searchTff7b72=Ta5d6ff"Ta5d6ffUniqueSearchUATa5d6ff"Tb4b4b4)
Tff7b72assert Te6edf3n Tff7b72>Tff7b72= T79c0ff1
Tff7b72def Td2a8fftest_outcome_filterTb4b4b4(Te6edf3daoTb4b4b4)Tb4b4b4:
Te6edf3ih Tff7b72= Te6edf3_id_hashTb4b4b4(Tb4b4b4)
Te6edf3daoTff7b72.Td2a8ffinsertTb4b4b4(Te6edf3ihTb4b4b4, Ta5d6ff"Ta5d6ff10.0.0.3Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffbTa5d6ff"Tb4b4b4, Te6edf3SETUP_PATHTb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffinvalid_jsonTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Te6edf3only Tff7b72= Te6edf3daoTff7b72.Td2a8fflist_attemptsTb4b4b4(Te6edf3outcomeTff7b72=Ta5d6ff"Ta5d6ffinvalid_jsonTa5d6ff"Tb4b4b4, Te6edf3limitTff7b72=T79c0ff100Tb4b4b4)
Tff7b72assert Tffa657allTb4b4b4(Te6edf3rTb4b4b4[Ta5d6ff"Ta5d6ffoutcomeTa5d6ff"Tb4b4b4] Tff7b72== Ta5d6ff"Ta5d6ffinvalid_jsonTa5d6ff" Tff7b72for Te6edf3r Tff7b72in Te6edf3onlyTb4b4b4)
Tff7b72def Td2a8fftest_is_trusted_and_upsertTb4b4b4(Te6edf3daoTb4b4b4)Tb4b4b4:
Te6edf3ih Tff7b72= Te6edf3_id_hashTb4b4b4(Tb4b4b4)
Te6edf3ua Tff7b72= Ta5d6ff"Ta5d6ffTrustedClient/2Ta5d6ff"
Te6edf3h Tff7b72= Te6edf3user_agent_hashTb4b4b4(Te6edf3uaTb4b4b4)
Tff7b72assert Te6edf3daoTff7b72.Td2a8ffis_trustedTb4b4b4(Te6edf3ihTb4b4b4, Ta5d6ff"Ta5d6ff10.0.0.4Ta5d6ff"Tb4b4b4, Te6edf3hTb4b4b4) Tff7b72is Tff7b72False
Te6edf3daoTff7b72.Td2a8ffupsert_trustedTb4b4b4(Te6edf3ihTb4b4b4, Ta5d6ff"Ta5d6ff10.0.0.4Ta5d6ff"Tb4b4b4, Te6edf3hTb4b4b4)
Tff7b72assert Te6edf3daoTff7b72.Td2a8ffis_trustedTb4b4b4(Te6edf3ihTb4b4b4, Ta5d6ff"Ta5d6ff10.0.0.4Ta5d6ff"Tb4b4b4, Te6edf3hTb4b4b4) Tff7b72is Tff7b72True
Tff7b72def Td2a8fftest_count_lockout_excludes_trusted_fingerprintTb4b4b4(Te6edf3daoTb4b4b4)Tb4b4b4:
Te6edf3ih Tff7b72= Te6edf3_id_hashTb4b4b4(Tb4b4b4)
Te6edf3ip Tff7b72= Ta5d6ff"Ta5d6ff10.0.0.5Ta5d6ff"
Te6edf3ua_ok Tff7b72= Ta5d6ff"Ta5d6ffOkBrowserTa5d6ff"
Te6edf3ua_bad Tff7b72= Ta5d6ff"Ta5d6ffBadBrowserTa5d6ff"
Te6edf3h_ok Tff7b72= Te6edf3user_agent_hashTb4b4b4(Te6edf3ua_okTb4b4b4)
Te6edf3daoTff7b72.Td2a8ffupsert_trustedTb4b4b4(Te6edf3ihTb4b4b4, Te6edf3ipTb4b4b4, Te6edf3h_okTb4b4b4)
Te6edf3since Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72- T79c0ff100
Tff7b72for Te6edf3_ Tff7b72in Tffa657rangeTb4b4b4(T79c0ff6Tb4b4b4)Tb4b4b4:
Te6edf3daoTff7b72.Td2a8ffinsertTb4b4b4(Te6edf3ihTb4b4b4, Te6edf3ipTb4b4b4, Te6edf3ua_okTb4b4b4, Te6edf3LOGIN_PATHTb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fffailed_passwordTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72assert Te6edf3daoTff7b72.Td2a8ffcount_lockout_failuresTb4b4b4(Te6edf3ihTb4b4b4, Te6edf3ipTb4b4b4, Te6edf3sinceTb4b4b4) Tff7b72== T79c0ff0
Tff7b72for Te6edf3_ Tff7b72in Tffa657rangeTb4b4b4(T79c0ff5Tb4b4b4)Tb4b4b4:
Te6edf3daoTff7b72.Td2a8ffinsertTb4b4b4(Te6edf3ihTb4b4b4, Te6edf3ipTb4b4b4, Te6edf3ua_badTb4b4b4, Te6edf3LOGIN_PATHTb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fffailed_passwordTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72assert Te6edf3daoTff7b72.Td2a8ffcount_lockout_failuresTb4b4b4(Te6edf3ihTb4b4b4, Te6edf3ipTb4b4b4, Te6edf3sinceTb4b4b4) Tff7b72== T79c0ff5
Tff7b72def Td2a8fftest_prune_trusted_keeps_under_capTb4b4b4(Te6edf3daoTb4b4b4)Tb4b4b4:
Te6edf3ih Tff7b72= Te6edf3_id_hashTb4b4b4(Tb4b4b4)
Te6edf3ip Tff7b72= Ta5d6ff"Ta5d6ff10.0.0.6Ta5d6ff"
Tff7b72for Te6edf3i Tff7b72in Tffa657rangeTb4b4b4(Te6edf3MAX_TRUSTED_FINGERPRINTS_PER_IDENTITY Tff7b72+ T79c0ff5Tb4b4b4)Tb4b4b4:
Te6edf3ua Tff7b72= Ta5d6fffTa5d6ff"Ta5d6ffBrowser-Tffd700{Te6edf3iTffd700}Ta5d6ff"
Te6edf3daoTff7b72.Td2a8ffupsert_trustedTb4b4b4(Te6edf3ihTb4b4b4, Te6edf3ipTb4b4b4, Te6edf3user_agent_hashTb4b4b4(Te6edf3uaTb4b4b4)Tb4b4b4)
Te6edf3row Tff7b72= Te6edf3daoTff7b72.Td2a8ffproviderTff7b72.Td2a8fffetchoneTb4b4b4(
Ta5d6ff"Ta5d6ffSELECT COUNT(*) AS c FROM trusted_login_clients WHERE identity_hash = ?Ta5d6ff"Tb4b4b4,
Tb4b4b4(Te6edf3ihTb4b4b4,Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72assert Tffa657intTb4b4b4(Te6edf3rowTb4b4b4[Ta5d6ff"Ta5d6ffcTa5d6ff"Tb4b4b4]Tb4b4b4) Tff7b72== Te6edf3MAX_TRUSTED_FINGERPRINTS_PER_IDENTITY
Tff7b72def Td2a8fftest_cleanup_old_removes_oldest_when_over_maxTb4b4b4(Te6edf3daoTb4b4b4)Tb4b4b4:
Te6edf3ih Tff7b72= Te6edf3_id_hashTb4b4b4(Tb4b4b4)
Te6edf3daoTff7b72.Td2a8ffcleanup_oldTb4b4b4(Te6edf3max_rowsTff7b72=T79c0ff3Tb4b4b4)
Tff7b72for Te6edf3i Tff7b72in Tffa657rangeTb4b4b4(T79c0ff5Tb4b4b4)Tb4b4b4:
Te6edf3daoTff7b72.Td2a8ffinsertTb4b4b4(Te6edf3ihTb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ff10.0.1.Tffd700{Te6edf3iTffd700}Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffxTa5d6ff"Tb4b4b4, Te6edf3LOGIN_PATHTb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffsuccessTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Te6edf3daoTff7b72.Td2a8ffcleanup_oldTb4b4b4(Te6edf3max_rowsTff7b72=T79c0ff3Tb4b4b4)
Te6edf3n Tff7b72= Te6edf3daoTff7b72.Td2a8ffcount_attemptsTb4b4b4(Tb4b4b4)
Tff7b72assert Te6edf3n Tff7b72== T79c0ff3
Tf0883e@settingsTb4b4b4(Te6edf3max_examplesTff7b72=T79c0ff30Tb4b4b4, Te6edf3suppress_health_checkTff7b72=Tb4b4b4[Te6edf3HealthCheckTff7b72.Td2a8fffunction_scoped_fixtureTb4b4b4]Tb4b4b4)
Tf0883e@givenTb4b4b4(
Te6edf3ipTff7b72=Te6edf3stTff7b72.Td2a8ffip_addressesTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffmapTb4b4b4(Tffa657strTb4b4b4)Tb4b4b4,
Te6edf3uaTff7b72=Te6edf3stTff7b72.Td2a8fftextTb4b4b4(
Te6edf3alphabetTff7b72=Te6edf3stTff7b72.Td2a8ffcharactersTb4b4b4(Te6edf3min_codepointTff7b72=T79c0ff32Tb4b4b4, Te6edf3max_codepointTff7b72=T79c0ff126Tb4b4b4)Tb4b4b4,
Te6edf3min_sizeTff7b72=T79c0ff0Tb4b4b4,
Te6edf3max_sizeTff7b72=T79c0ff200Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Te6edf3outcomeTff7b72=Te6edf3stTff7b72.Td2a8ffsampled_fromTb4b4b4(
Tb4b4b4[Ta5d6ff"Ta5d6ffsuccessTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fffailed_passwordTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffrate_limitedTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffinvalid_jsonTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72def Td2a8fftest_insert_list_hypothesis_invariantsTb4b4b4(Te6edf3daoTb4b4b4, Te6edf3ipTb4b4b4, Te6edf3uaTb4b4b4, Te6edf3outcomeTb4b4b4)Tb4b4b4:
Te6edf3assumeTb4b4b4(Te6edf3ipTb4b4b4)
Te6edf3ih Tff7b72= Te6edf3_id_hashTb4b4b4(Tb4b4b4)
Te6edf3before_total Tff7b72= Te6edf3daoTff7b72.Td2a8ffcount_attemptsTb4b4b4(Tb4b4b4)
Te6edf3daoTff7b72.Td2a8ffinsertTb4b4b4(Te6edf3ihTb4b4b4, Te6edf3ipTb4b4b4, Te6edf3uaTb4b4b4, Te6edf3LOGIN_PATHTb4b4b4, Ta5d6ff"Ta5d6ffPOSTTa5d6ff"Tb4b4b4, Te6edf3outcomeTb4b4b4, Ta5d6ff"Ta5d6ffhTa5d6ff"Tb4b4b4)
Te6edf3after_total Tff7b72= Te6edf3daoTff7b72.Td2a8ffcount_attemptsTb4b4b4(Tb4b4b4)
Tff7b72assert Te6edf3after_total Tff7b72== Te6edf3before_total Tff7b72+ T79c0ff1
Te6edf3rows Tff7b72= Te6edf3daoTff7b72.Td2a8fflist_attemptsTb4b4b4(Te6edf3limitTff7b72=T79c0ff500Tb4b4b4, Te6edf3offsetTff7b72=T79c0ff0Tb4b4b4, Te6edf3outcomeTff7b72=Te6edf3outcomeTb4b4b4)
Tff7b72assert Tffa657anyTb4b4b4(Te6edf3rTb4b4b4[Ta5d6ff"Ta5d6ffclient_ipTa5d6ff"Tb4b4b4] Tff7b72== Te6edf3ip Tff7b72and Te6edf3rTb4b4b4[Ta5d6ff"Ta5d6ffoutcomeTa5d6ff"Tb4b4b4] Tff7b72== Te6edf3outcome Tff7b72for Te6edf3r Tff7b72in Te6edf3rowsTb4b4b4)
Tff7b72def Td2a8fftest_access_attempts_table_existsTb4b4b4(Te6edf3dbTb4b4b4)Tb4b4b4:
Te6edf3row Tff7b72= Te6edf3dbTff7b72.Td2a8ffproviderTff7b72.Td2a8fffetchoneTb4b4b4(
Ta5d6ff"Ta5d6ffSELECT name FROM sqlite_master WHERE type=Ta5d6ff'Ta5d6fftableTa5d6ff'Ta5d6ff AND name=Ta5d6ff'Ta5d6ffaccess_attemptsTa5d6ff'Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3row Tff7b72is Tff7b72not Tff7b72None
Te6edf3row2 Tff7b72= Te6edf3dbTff7b72.Td2a8ffproviderTff7b72.Td2a8fffetchoneTb4b4b4(
Ta5d6ff"Ta5d6ffSELECT name FROM sqlite_master WHERE type=Ta5d6ff'Ta5d6fftableTa5d6ff'Ta5d6ff AND name=Ta5d6ff'Ta5d6fftrusted_login_clientsTa5d6ff'Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3row2 Tff7b72is Tff7b72not Tff7b72None
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────